package world

import (
	"server/world/entity"
	"server/world/scene"
	"sync"
)

// World 大世界系统
type World struct {
	sceneManager      *scene.SceneManager
	players           map[int64]*scene.Player
	playerScenes      map[int64]int // 记录玩家所在的场景实例ID
	npcs              map[string]*entity.NPC
		monsters          map[string]*entity.Monster
		items             map[string]*entity.Item
	obstacles         map[string]*entity.Obstacle
	entitiesLock      sync.RWMutex
	defaultMaxPlayers int         // 默认场景最大玩家数
}

// NewWorld 创建新的大世界系统
func NewWorld() *World {
	w := &World{
		sceneManager:      scene.NewSceneManager(),
		players:           make(map[int64]*scene.Player),
	playerScenes:      make(map[int64]int),
		npcs:              make(map[string]*entity.NPC),
		monsters:          make(map[string]*entity.Monster),
		items:             make(map[string]*entity.Item),
		obstacles:         make(map[string]*entity.Obstacle),
		defaultMaxPlayers: 100, // 默认场景最大玩家数为100
	}

	// 创建一个默认场景，使用层ID 0
	w.sceneManager.AddLayerScene(1, 0, w.defaultMaxPlayers, 1000, 1000, 10)

	return w
}

// AddPlayer 添加玩家到世界
func (w *World) AddPlayer(p *scene.Player, sceneID int) (int, bool) {
	// 查找可用的场景层
	scene, layerID, available := w.sceneManager.GetAvailableSceneLayer(sceneID)

	// 如果没有可用层，创建新层
	if !available {
		var created bool
		scene, layerID, created = w.sceneManager.CreateNewSceneLayer(sceneID, w.defaultMaxPlayers, 1000, 1000, 10)
		if !created {
			return 0, false
		}
	}

	w.entitiesLock.Lock()
	defer w.entitiesLock.Unlock()

	// 添加到场景
	added := scene.Add(p)
	if !added {
		// 可能在检查可用层和实际添加之间，场景已经满了
		return 0, false
	}

	// 添加到玩家集合
	w.players[p.ID] = p
	// 记录玩家所在的场景实例ID
	w.playerScenes[p.ID] = int(scene.GetID())

	// 发送初始数据给玩家
	nearbyEntities := scene.GetNearEntities(p, 300, scene.EntityTypePlayer)
	nearbyPlayers := make([]*scene.Player, 0, len(nearbyEntities))
	for _, entity := range nearbyEntities {
		// 类型断言转换为Player
		if player, ok := entity.(*scene.Player); ok {
			nearbyPlayers = append(nearbyPlayers, player)
		}
	}
	p.SendInitialData(nearbyPlayers)



	// 返回玩家所在的场景层ID
	return layerID, true
}

// RemovePlayer 从世界移除玩家
func (w *World) RemovePlayer(playerID int64) {
	w.entitiesLock.Lock()
	defer w.entitiesLock.Unlock()

	if p, exists := w.players[playerID]; exists {
		// 获取玩家所在的场景实例ID
		sceneInstanceID, sceneExists := w.playerScenes[playerID]
		if sceneExists {
			// 从场景中移除
			scene, exists := w.sceneManager.GetScene(sceneInstanceID)
			if exists {
				scene.Remove(p)
			}
			// 清理玩家场景记录
			delete(w.playerScenes, playerID)
		}

		// 从玩家集合中移除
		delete(w.players, playerID)
		
	}
}

// HandlePlayerInput 处理玩家输入
func (w *World) HandlePlayerInput(playerID int64, input scene.PlayerInputMessage) {
	w.entitiesLock.RLock()
	p, exists := w.players[playerID]
	sceneInstanceID, sceneExists := w.playerScenes[playerID]
	w.entitiesLock.RUnlock()

	if !exists || !sceneExists {
		return
	}

	// 获取玩家所在场景
	scene, exists := w.sceneManager.GetScene(sceneInstanceID)
	if !exists {
		return
	}

	// 处理输入
	p.HandleInput(input, scene.Width(), scene.Height())

	// 更新场景中的实体位置
	scene.Move(p, p.GetX(), p.GetY())

	// 通知附近玩家位置变化
	nearbyEntities := scene.GetNearEntities(p, 300, scene.EntityTypePlayer)
	nearbyPlayers := make([]*scene.Player, 0, len(nearbyEntities))
	for _, entity := range nearbyEntities {
		if player, ok := entity.(*scene.Player); ok {
			nearbyPlayers = append(nearbyPlayers, player)
		}
	}
	p.NotifyMovement(nearbyPlayers)
}

// Update 世界主循环更新
func (w *World) Update() {
	// 可以实现定时更新逻辑
	// 例如更新实体状态、检测碰撞、发送AOI更新等
}

// AddNPC 添加NPC实体
func (w *World) AddNPC(npc *entity.NPC, sceneID int) bool {
	scene, exists := w.sceneManager.GetScene(sceneID)
	if !exists {
		return false
	}

	w.entitiesLock.Lock()
	defer w.entitiesLock.Unlock()

	scene.Add(npc)
	w.npcs[npc.GetID()] = npc
	return true
}

// AddMonster 添加怪物实体
func (w *World) AddMonster(monster *entity.Monster, sceneID int) bool {
	scene, exists := w.sceneManager.GetScene(sceneID)
	if !exists {
		return false
	}

	w.entitiesLock.Lock()
	defer w.entitiesLock.Unlock()

	scene.Add(monster)
	w.monsters[monster.GetID()] = monster
	return true
}

// AddItem 添加物品实体
func (w *World) AddItem(item *entity.Item, sceneID int) bool {
	scene, exists := w.sceneManager.GetScene(sceneID)
	if !exists {
		return false
	}

	w.entitiesLock.Lock()
	defer w.entitiesLock.Unlock()

	scene.Add(item)
	w.items[item.GetID()] = item
	return true
}

// AddObstacle 添加障碍物实体
func (w *World) AddObstacle(obstacle *entity.Obstacle, sceneID int) bool {
	scene, exists := w.sceneManager.GetScene(sceneID)
	if !exists {
		return false
	}

	w.entitiesLock.Lock()
	defer w.entitiesLock.Unlock()

	scene.Add(obstacle)
	w.obstacles[obstacle.GetID()] = obstacle
	return true
}
